package com.eastfair.venueservice.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
//import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.eastfair.boot.request.PageParams;
import com.eastfair.boot.service.SuperServiceImpl;
import com.eastfair.constant.BusinessConstant;
import com.eastfair.core.base.R;
import com.eastfair.core.context.ContextUtil;
import com.eastfair.venueservice.dao.ServiceBorrowReturnMapper;
import com.eastfair.venueservice.dto.ServiceBorrowReturnDTO;
import com.eastfair.venueservice.dto.ServiceInventoryInFlowDTO;
import com.eastfair.venueservice.dto.ServiceInventoryOutFlowDTO;
import com.eastfair.venueservice.entity.ServiceBorrowReturn;
import com.eastfair.venueservice.enumeration.ServiceBorrowReturnGoodsLossStateEnum;
import com.eastfair.venueservice.enumeration.ServiceBorrowReturnReturnStateEnum;
import com.eastfair.venueservice.enumeration.ServiceInventoryInFlowInStockTypeEnum;
import com.eastfair.venueservice.enumeration.ServiceInventoryOutFlowOutStockTypeEnum;
import com.eastfair.venueservice.service.ServiceBorrowReturnService;
import com.eastfair.venueservice.service.ServiceInventoryInFlowService;
import com.eastfair.venueservice.service.ServiceInventoryOutFlowService;
import com.eastfair.venueservice.service.ServiceLossService;
import com.eastfair.venueservice.vo.ServiceBorrowReturnVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDate;
import java.util.Collection;
import java.util.List;

/**
 * <p>
 * 业务实现类
 * 借用归还记录
 * </p>
 *
 * @author linan
 * @date 2022-09-19
 */
@Slf4j
@Service
//@DS("#thread.tenant")
public class ServiceBorrowReturnServiceImpl extends SuperServiceImpl<ServiceBorrowReturnMapper, ServiceBorrowReturn> implements ServiceBorrowReturnService {

    @Resource
    private ServiceBorrowReturnMapper serviceBorrowReturnMapper;

    @Resource
    private ServiceLossService serviceLossService;

    @Resource
    private ServiceInventoryInFlowService serviceInventoryInFlowService;

    @Resource
    private ServiceInventoryOutFlowService serviceInventoryOutFlowService;

    /**
     * 处理逻辑删除相关处理
     *
     * @param modelList 实体
     * @return 是否成功
     */
    @Override
    protected R<Boolean> handlerRemoveByIdsOfLogic(Collection<ServiceBorrowReturn> modelList) {
        modelList.forEach(s -> s.setIsDeleted(BusinessConstant.YES));
        return R.successDef();
    }

    @Override
    protected R<Boolean> handlerSave(ServiceBorrowReturn model) {
        model.setProjectId(ContextUtil.getProjectId());
        model.setSubsystemId(ContextUtil.getSubSystemId());
        return R.successDef();
    }

    @Override
    public Page<ServiceBorrowReturnVO> listServiceBorrowReturnVOs(PageParams<ServiceBorrowReturnDTO> pageParams) {
        log.info("listServiceBorrowReturnVOs - 分页查询借还记录VO列表, pageParams={}", pageParams);
        ServiceBorrowReturnDTO query = pageParams.getModel();
        Page<ServiceBorrowReturn> page = pageParams.buildPage();
        QueryWrapper<ServiceBorrowReturn> queryWrapper = createServiceBorrowReturnVOQueryWrapper(query);
        return serviceBorrowReturnMapper.listServiceBorrowReturnVOs(page, queryWrapper);
    }

    @Override
    public ServiceBorrowReturnVO getServiceBorrowReturnVOById(Long id) {
        log.info("getServiceBorrowReturnVOById - ID获取借还记录, id={}", id);
        ServiceBorrowReturn serviceBorrowReturn = getById(id);
        if (serviceBorrowReturn == null) {
            return null;
        }
        return BeanUtil.toBean(serviceBorrowReturn, ServiceBorrowReturnVO.class);
    }

    @Override
    public List<ServiceBorrowReturn> listServiceBorrowReturns(ServiceBorrowReturnDTO query) {
        log.info("listServiceBorrowReturns - 查询借还记录, query={}", query);
        QueryWrapper<ServiceBorrowReturn> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda()
                .eq(ServiceBorrowReturn::getIsDeleted, BusinessConstant.DELETE_NO)
                .eq(query.getReturnState() != null, ServiceBorrowReturn::getReturnState, query.getReturnState())
                .eq(StrUtil.isNotBlank(query.getInventoryCode()), ServiceBorrowReturn::getInventoryCode, query.getInventoryCode())
        ;
        return list(queryWrapper);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean saveServiceBorrowReturn(ServiceBorrowReturnDTO serviceBorrowReturnDTO) {
        log.info("saveServiceBorrowReturn - 保存借还记录, serviceBorrowReturnDTO={}", serviceBorrowReturnDTO);
        ServiceBorrowReturn serviceBorrowReturn = BeanUtil.toBean(serviceBorrowReturnDTO, ServiceBorrowReturn.class);
        return save(serviceBorrowReturn);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateServiceBorrowReturn(ServiceBorrowReturnDTO serviceBorrowReturnDTO) {
        log.info("updateServiceBorrowReturn - 更新借还记录");
        ServiceBorrowReturn serviceBorrowReturn = BeanUtil.toBean(serviceBorrowReturnDTO, ServiceBorrowReturn.class);
        return updateById(serviceBorrowReturn);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean borrowService(ServiceBorrowReturnDTO serviceBorrowReturnDTO) {
        log.info("borrowService - 借用服务, serviceBorrowReturnDTO={}", serviceBorrowReturnDTO);
        // 保存借用记录
        serviceBorrowReturnDTO.setReturnState(ServiceBorrowReturnReturnStateEnum.NO);
        saveServiceBorrowReturn(serviceBorrowReturnDTO);
        // 保存出库记录
        ServiceInventoryOutFlowDTO serviceInventoryOutFlowDTO = new ServiceInventoryOutFlowDTO();
        serviceInventoryOutFlowDTO.setInventoryCode(serviceBorrowReturnDTO.getInventoryCode());
        serviceInventoryOutFlowDTO.setOutNum(serviceBorrowReturnDTO.getBorrowNum());
        serviceInventoryOutFlowDTO.setOutStockType(ServiceInventoryOutFlowOutStockTypeEnum.BORROW);
        serviceInventoryOutFlowDTO.setExhibitionManageId(serviceBorrowReturnDTO.getExhibitionManageId());
        return serviceInventoryOutFlowService.saveOutFlow(serviceInventoryOutFlowDTO);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean returnService(ServiceBorrowReturnDTO serviceBorrowReturnDTO) {
        log.info("returnService - 归还服务, serviceBorrowReturnDTO={}", serviceBorrowReturnDTO);
        // 更新归还记录
        serviceBorrowReturnDTO.setReturnState(ServiceBorrowReturnReturnStateEnum.YES);
        updateServiceBorrowReturn(serviceBorrowReturnDTO);
        // 保存报损记录
        if (!serviceBorrowReturnDTO.getGoodsLossState().eq(ServiceBorrowReturnGoodsLossStateEnum.UNDAMAGED)) {
            return serviceLossService.returnServiceLoss(serviceBorrowReturnDTO);
        }
        // 保存入库记录
        ServiceInventoryInFlowDTO serviceInventoryInFlowDTO = new ServiceInventoryInFlowDTO();
        serviceInventoryInFlowDTO.setInventoryCode(serviceBorrowReturnDTO.getInventoryCode());
        serviceInventoryInFlowDTO.setInNum(serviceBorrowReturnDTO.getBorrowNum());
        serviceInventoryInFlowDTO.setInStockType(ServiceInventoryInFlowInStockTypeEnum.RETURN);
        serviceInventoryInFlowDTO.setExhibitionManageId(serviceBorrowReturnDTO.getExhibitionManageId());
        serviceInventoryInFlowDTO.setGoodsLossState(serviceBorrowReturnDTO.getGoodsLossState());
        return serviceInventoryInFlowService.saveInFlow(serviceInventoryInFlowDTO);
    }

    /**
     * 生成 ServiceBorrowReturnVO 的查询.
     *
     * @param query ServiceBorrowReturnDTO
     * @return QueryWrapper
     */
    private QueryWrapper<ServiceBorrowReturn> createServiceBorrowReturnVOQueryWrapper(ServiceBorrowReturnDTO query) {
        QueryWrapper<ServiceBorrowReturn> queryWrapper = new QueryWrapper<>();
        queryWrapper
                .eq("sbr.is_deleted", BusinessConstant.DELETE_NO)
                .eq(query.getExhibitionManageId() != null, "si.exhibition_manage_id", query.getExhibitionManageId())
                .eq(query.getServiceProviderId() != null, "si.service_provider_id", query.getServiceProviderId())
                .eq(StrUtil.isNotBlank(query.getServiceProviderType()), "si.service_provider_type", query.getServiceProviderType())
                .like(StrUtil.isNotBlank(query.getServiceName()), "si.service_name", query.getServiceName())
                .like(StrUtil.isNotBlank(query.getServiceSpecsName()),"sp.service_specs_name", query.getServiceSpecsName())
                .eq(query.getServiceCategoryId() != null, "siv.service_category_id", query.getServiceCategoryId())
                .eq(StrUtil.isNotBlank(query.getInventoryCode()), "siv.inventory_code", query.getInventoryCode())
                .eq(query.getReturnState() != null, "sbr.return_state", query.getReturnState())
                .between(StrUtil.isNotBlank(query.getBorrowStartTime()) && StrUtil.isNotBlank(query.getBorrowEndTime()),
                        "sbr.create_time", query.getBorrowStartTime(), query.getBorrowEndTime())
                .between(StrUtil.isNotBlank(query.getReturnStartTime()) && StrUtil.isNotBlank(query.getReturnEndTime()),
                        "sbr.update_time", query.getReturnStartTime(), query.getReturnEndTime())
                // 查询逾期未归还的服务
                .and(query.getIsOverDueQuery() != null && query.getIsOverDueQuery(), overdueQueryWrapper -> overdueQueryWrapper
                        .eq("sbr.return_state", ServiceBorrowReturnReturnStateEnum.NO)
                        .lt("sbr.expected_return_date", LocalDate.now()))
        ;
        // 以借用 或 归还 的操作时间倒序
        if (ServiceBorrowReturnReturnStateEnum.YES.eq(query.getReturnState())) {
            queryWrapper.orderByDesc("sbr.update_time");
        } else {
            queryWrapper.orderByDesc("sbr.create_time");
        }
        return queryWrapper;
    }
}
